package collection

/**
 * Created by Administrator on 2019/09/11.
 */
data class Ps(val name:String){
    var age:Int = 12
}

fun main(args:Array<String>){
    var ps1 = Ps("Jon")
    var ps2 = Ps("Jon")
    ps1.age = 32
    ps2.age = 43
    var ps3 = ps1.copy(name = "mick")
    println("ps1 == ps2 ? ==>${ps1 == ps2}")
    println("ps1 with age ${ps1.age} ==> ${ps1}")
    println("ps1 with age ${ps2.age} ==> ${ps2}")

    var ins = arrayOf(1,2,3)

    val any = Array<Any>(3){""}
    copy(ins, any)

    var list = listOf(1,2,3,4,5)
    list.foldRight(0, {
        acc:Int, i:Int->
        println("acc = $acc, i = $i")
        val res = acc + i
        println("result = $res")
        res
    })

    val words = "A long time ago in a galaxy far far away".split(" ")
    val shortWords = mutableListOf<String>()
    words.getShortWordsTo(shortWords, 3)
    println(shortWords)

    val mp1 = mutableMapOf<String, Int>().apply { this["key1"]=1; this["key2"] = 2 }
    mp1.put("key3", 3)
    println(mp1.get("key3"))

    val douted = List(5, {it * 2})
    douted.forEach { println(it) }

    val ns = listOf("one", "two", "three", "four")
    println(ns.associateBy { it.length })

    var sq = generateSequence(3){it + 2}
    println(sq.take(10).toList())

//    val numbers = listOf("one", "two", "three", "four")
//    val result = numbers.mapTo(HashSet()) { it.length }
//    println("distinct item lengths are $result")

//    val numbers = mutableListOf("one", "two", "three", "four")
//    val sortedNumbers = numbers.sorted()
//    println(numbers == sortedNumbers)  // false
//    numbers.sort()
//    println(numbers == sortedNumbers)  // tru

    println("------------------------------------numbers test-------------------------------------------")
    val numbers = setOf(1, 2, 3)
    println(numbers.map { it * 3 })
    println(numbers.mapIndexed { idx, value -> value * idx })

    println(numbers.mapNotNull { if ( it == 2) null else it * 3 })
    println(numbers.mapIndexedNotNull { idx, value -> if (idx == 0) null else value * idx })

    val colors = listOf("red", "brown", "grey")
    println(colors.associateBy { it.length })

    val animals = listOf("fox", "bear", "wolf")
    println(colors zip animals)
    println(colors.zip(animals) { color, animal -> "The ${animal.capitalize()} is $color"})

    val twoAnimals = listOf("fox", "bear")
    println(colors.zip(twoAnimals))

    val numberPairs = listOf("one" to 1, "two" to 2, "three" to 3, "four" to 4)
    println(numberPairs.unzip())

    data class FullName(val firstName:String, val lastName:String)

    fun parseFull(name:String) : FullName{
        var ar = name.split(" ")
        if(ar.size == 2){
            return FullName(ar[0], ar[1])
        }else throw Exception("parse err")
    }

    val names = listOf("ali davy", "honey sweet", "john swift")
    val mp = names.associate { name->parseFull(name).let { it.firstName to it.lastName}}

    println(mp.keys)

    val numberSets = listOf(setOf(1, 2, 3), setOf(4, 5, 6), setOf(1, 2))
    println(numberSets.flatten())

    println(numbers.joinToString(separator = " | ", prefix = "start: ", postfix = ": end"))

    val nums = (1..100).toList()
    println(nums.joinToString(limit = 10, truncated = "more..."))

    val cs = listOf("one", "two", "three", "four")
    println(cs.any { it.endsWith("e") })
    println(cs.none { it.endsWith("a") })
    println(cs.all { it.endsWith("e") })

    val cs2 = cs + "five"
    println(cs2)

    println(cs2 - listOf("one", "five"))

    println(cs2.groupBy { it.first().toUpperCase() })
    println(cs2.groupingBy { it.first() }.eachCount())
    println(cs2.groupBy(keySelector = { it.first() }, valueTransform = { it.toUpperCase() }))

    println(cs2.chunked(3))
    println(cs2.windowed(3))

    val ds = (1..10).toList()
    println(ds.windowed(3, step = 2, partialWindows = true))

    println(ds.elementAtOrNull(10))
    println(ds.elementAtOrElse(10){index -> "the value of index = $index not found"})
    println(ds.first(){it > 2})
    println(ds.last(){it < 10 })
    println(ds.find { it == 1 })

    println("Sorted by length ascending: ${cs2.sortedBy { it.length }}")

    println(ds.minBy { it % 3 })
    println(cs2.maxWith(compareBy { it.length }))

    println(ds.sumBy { it * 2 })

    println(ds.reduce { acc, i -> acc + i })
    println(ds.reduceRight { i, acc ->  i + acc})
    println(ds.fold(0) { acc, i -> acc + i })

    println(ds.getOrElse(15, {it}))

    println(ds.binarySearch(3))

    println(names.sortedBy { it.length })
    println(names.sortedByDescending { it.last() })

    println(names.sortedWith(compareBy<String> { it.length }.thenBy { it }))

    val num2 = setOf("one", "two", "three")
    println(num2 union setOf("four", "five"))

    println(num2 intersect setOf("two", "one"))

    println(num2 subtract setOf("four", "five"))
}

fun List<String>.getShortWordsTo(shortWords: MutableList<String>, maxLength: Int) {
    this.filterTo(shortWords) { it.length <= maxLength }
    // throwing away the articles
    val articles = setOf("a", "A", "an", "An", "the", "The")
    shortWords -= articles
}

fun copy(from: Array<out Any>, to: Array<Any>) {
    assert(from.size == to.size)
    for (i in from.indices)
        to[i] = from[i]
}